#ifndef QUEUE_H
#define QUEUE_H

#include <iostream>

#include "queue_element.h"

template<typename T>
class Queue
{
protected:
    Queue_Element<T> *first;
    Queue_Element<T> *last;
public:

    enum Error { EMPTY_QUEUE };

    Queue() : first(0), last(0)
    {
    }

    virtual ~Queue()
    {
        clear();
    }

    void clear()
    {
        if (first && last)
        {
            Queue_Element<T> *p = first;
            Queue_Element<T> *q = first->next;
            while (p && q)
            {
                delete p;
                p = q;
                q = q->next;
            }
            if (p) delete p;
            first = 0;
            last = 0;
        }
    }

    void push(const T &elem)
    {
        if (isEmpty())
        {
            first=new Queue_Element<T>(elem);
            last = first;
        }
        else if (last)
        {
            last->next = new Queue_Element<T>(elem);
            last=last->next;
        }
        else throw EMPTY_QUEUE;
    }
    void pop()
    {
        if (!isEmpty())
        {
            Queue_Element<T> *p=first;
            first=first->next;
            delete p;
            if (!first)
            {
                last = first;
            }
        }
        else throw EMPTY_QUEUE;
    }

    const T& front() const
    {
        if (!isEmpty())
        {
            return (*first->data);
        }
        else throw EMPTY_QUEUE;
    }

    bool isEmpty() const
    {
        return !first && !last;
    }
};


#endif // QUEUE_H
